{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n"
     ]
    }
   ],
   "source": [
    "import torchdyn\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import matplotlib.pyplot as plt\n",
    "from torchdyn.numerics import AsynchronousLeapfrog\n",
    "from torchdyn.numerics import odeint, odeint_symplectic\n",
    "\n",
    "import torchdiffeq\n",
    "import time \n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "metadata": {},
   "outputs": [],
   "source": [
    "vf = nn.Sequential(nn.Linear(2, 32), nn.Tanh(), nn.Linear(32, 2))\n",
    "class TestSystem(nn.Module):\n",
    "    def __init__(self, vf):\n",
    "        super().__init__()\n",
    "        self.nfe = 0\n",
    "        self.vf = vf\n",
    "        self.order = 1\n",
    "\n",
    "    def forward(self, t, x):\n",
    "        self.nfe += 1\n",
    "        return self.vf(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 194,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = TestSystem(vf)\n",
    "x = torch.randn(1024, 2)\n",
    "t_span = torch.linspace(0, 4, 200)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Fixed--step bench"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 195,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1455554962158203\n",
      "0.12147045135498047\n"
     ]
    }
   ],
   "source": [
    "t0 = time.time()\n",
    "v = f(0., x)\n",
    "xv = torch.cat([x, v], -1)\n",
    "solver = AsynchronousLeapfrog(stepping_class='fixed')\n",
    "t_eval, sol1 = odeint_symplectic(f, xv, t_span, solver=solver)\n",
    "t_end1 = time.time() - t0\n",
    "print(t_end1)\n",
    "\n",
    "t0 = time.time()\n",
    "sol2 = torchdiffeq.odeint(f, x, t_span, method='midpoint')\n",
    "t_end2 = time.time() - t0\n",
    "print(t_end2)\n",
    "\n",
    "true_sol = torchdiffeq.odeint(f, x, t_span, method='dopri5', atol=1e-9, rtol=1e-9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 196,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f51d285e9a0>"
      ]
     },
     "execution_count": 196,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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c+6558ZDvaamhpqaGh2GF5FxT8EvY0JTU1PSYK+vr2fHjh096h5++OHMmTOHc889lzlz5sSn2tra+NUJRUQkOQV/lmT7trynnXYa//mf/wnAV7/6VVatWsUnPvEJvva1r3H++efT0dHBD37wA84444xhty+mra2N+vp6NmzYwMaNG+NTfX19j/sOAMyaNYs5c+awePHiHuF+5JFHqtcuIjIMCv4syfZteWOhD7Bs2TL27NlDTk4OK1as4IMf/CDLlw/thofuTiQSoa2tjba2Nvbs2cN5553Hxo0baWho6HHq26xZszjqqKO45JJL+vTcCwsLh72PIiLSl4I/S7J5W16AoqIimpubueCCC2hubuakk05i6dKl3HPPPbS2trJ69WpefPFF/vCHP3DzzTfT3t7O7NmzefDBBykqKuKpp57iy1/+MgUFBdTV1bF582buvvtu2traelwbvrm5me3bt3PKKadw6aWXcswxx3D00Udz1FFHpX0fAhERGTkKfoDrr4cRvi0v8+fDGL0tb6KVK1dSVFQUvy3x9OnTWb16NXfffTe7du3iX//1X/n1r3/NhAkT+O53v8uNN97I5z//eS6//HLuu+8+Zs2axT//8z/Hj0hUVFRQUFAQn+rr61mzZs1I/mZFRGQYFPxjwGjfljeZrq4u2traOHDgAM3Nzbz99ts888wzvPbaa/Hb8nZ2djJ//ny2bdtGbW0tZ599NgUFBVxzzTUsX76co446qs92dc67iMjYktHgN7NFwPeBHGC5u9/ea30+8BPgJGA3cIm7N5hZOfAEcDLwkLtfm/CYk4CHgEJgFXCdD/eGA+PotrxdXV00Nzfj7mzZsiV+aH7t2rUA7Nq1i5aWFjo6OigoKODss8/mwQcfpLCwkPz8fMyMdevWkZeXF//goUvPioiER8besc0sB7gHOA+YByw1s3m9ql0BNLn7HOB7wB1BeRvwLeCfkmz6PuAqYG4wLRr51mde79vyPvbYY3R1dbFz505eeOEFFi5c2OcxsdvyxoK990j4RN3d3Zx22mksX76cxsZGli9fTlNTE6+99hobNmyIX9UuEolgZsycOZPZs2dTVVVFZWUlxx57LBdeeCFr1qxh9+7dFBQU0NLSwltvvcUxxxxDQ0MD77zzDgA///nPM/AbEhGRTMhkV20hUO/um9y9A1gBLO5VZzHwcDD/BPAx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\n",
      "text/plain": [
       "<Figure size 576x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(8,3))\n",
    "ax = plt.subplot(111)\n",
    "line, _ = ax.plot((sol1[...,:2]-true_sol).detach().abs().mean(1), c='black')\n",
    "line.set_label('torchdyn')\n",
    "line, _ = ax.plot((sol2-true_sol).detach().abs().mean(1), c='red')\n",
    "line.set_label('torchdiffeq')\n",
    "ax.set_ylabel('error')\n",
    "ax.set_xlabel('time')\n",
    "plt.legend()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torchdyn",
   "language": "python",
   "name": "torchdyn"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
